/***************************************************************************
 * Copyright (C) 2023-, openlinyou, <linyouhappy@outlook.com>
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 ***************************************************************************/

#ifndef HEADER_OPEN_COM_HTTP_SERVER_H
#define HEADER_OPEN_COM_HTTP_SERVER_H

#include <vector>
#include <set>
#include <unordered_map>
#include <string.h>
#include "openserver.h"
#include "openssl.h"
#include "openhttps.h"

namespace open
{

////////////OpenHttpServerMsg//////////////////////
struct OpenHttpServerMsg : public OpenMsgProtoMsg
{
    bool isHttps_;
    std::string ip_;
    unsigned int port_;
    unsigned int port1_;
    std::string keyFile_;
    std::string certFile_;
    OpenHttpHandle handle_;
    std::vector<int> vectAccepts_;
    std::vector<int> vectClients_;

    OpenHttpServerMsg() :isHttps_(false), port_(80), port1_(0), handle_(0) {}
    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpServerMsg::MsgId(); }
};

////////////OpenHttpRegisterMsg//////////////////////
struct OpenHttpRegisterMsg : public OpenMsgProtoMsg
{
    int fd_;
    OpenHttpServerMsg serverInfo_;

    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpRegisterMsg::MsgId(); }
};

////////////OpenHttpAcceptMsg//////////////////////
struct OpenHttpAcceptMsg : public OpenMsgProtoMsg
{
    bool isHttps_;
    int clientId_;
    std::string ip_;
    unsigned int port_;
    unsigned int port1_;
    OpenHttpHandle handle_;

    OpenHttpAcceptMsg() : isHttps_(false), port_(80), port1_(0), handle_(0), clientId_(-1) {}
    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpAcceptMsg::MsgId(); }
};

////////////OpenHttpNoticeMsg//////////////////////
struct OpenHttpNoticeMsg : public OpenMsgProtoMsg
{
    int fd_;
    OpenHttpAcceptMsg clientInfo_;

    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpNoticeMsg::MsgId(); }
};

////////////OpenComHttpServer//////////////////////
class OpenComHttpServer : public OpenComSocket
{
    OpenHttpServerMsg serverInfo_;

    int listen_fd_;
    int listen_fd1_;
    unsigned int balance_;
    std::set<int> setAgentId_;
    std::vector<int> vectAgentId_;

    virtual void onSocketAccept(const OpenSocketMsg& msg);
    virtual void onSocketClose(const OpenSocketMsg& msg);
    virtual void onSocketOpen(const OpenSocketMsg& msg);
    virtual void onSocketError(const OpenSocketMsg& msg);
    virtual void onSocketWarning(const OpenSocketMsg& msg);

public:
    OpenComHttpServer();
    virtual ~OpenComHttpServer() {}
    virtual bool start(OpenServer* worker);
    virtual void onOpenMsgProto(OpenMsgProto& proto);
    virtual inline OpenCom* newCom() { return new OpenComHttpServer; }
};

////////////OpenComHttpAgent//////////////////////
class OpenComHttpAgent : public OpenComSocket
{
    struct Client
    {
        int fd_;
        int pid_;
        TlsContext* tls_;
        SslCtx* sslCtx_;
        TlsBuffer buffer_;
        OpenHttpAcceptMsg clientInfo_;
        std::shared_ptr<OpenHttpRequest> request_;
        OpenComHttpAgent* com_;

        bool isOpenCache_;
        bool isCreateSendFile_;
        OpenWriteFile cacheSendFile_;
        bool isCreateReceiveFile_;
        OpenWriteFile cacheReceiveFile_;

        Client();
        ~Client();
        bool start();
        void sendClient();
        void sendResponse();
        void sendRawBuffer();
        void sendBuffer();
        void open();
        void update(const char* data, size_t size);
        void onOpen();
        void onData(const char* data, size_t size);
        void close();

        void onClientClientData(int reqPid, const char* data, size_t size);
        void onClientClientClose(int reqPid);
    };

    OpenHttpServerMsg serverInfo_;

    SslCtx sslCtx_;
    std::unordered_map<int, Client> mapClient_;

    virtual void onSocketData(const OpenSocketMsg& msg);
    virtual void onSocketClose(const OpenSocketMsg& msg);
    virtual void onSocketOpen(const OpenSocketMsg& msg);
    virtual void onSocketError(const OpenSocketMsg& msg);
    virtual void onSocketWarning(const OpenSocketMsg& msg);
public:
    OpenComHttpAgent() : sslCtx_(true) {}
    virtual ~OpenComHttpAgent() {}
    virtual bool start(OpenServer* worker);
    void onOpenMsgProto(OpenMsgProto& proto);
    virtual inline OpenCom* newCom() { return new OpenComHttpAgent; }
};


};


#endif   //HEADER_OPEN_COM_HTTP_SERVER_H
